We are using the SHIVA trial to run a retrospective analysis to validate the PTD package. During the trial, the hormon receptors ER, AR and PR were colelcted using Immunohistochemistry (IHC). In the retrospective analisi we used the expression (as z-score) values collected from the RNA-seq data TCGA dataset. In this section we want to explore the relationship between RNA-seq and Immunohistochemistry and, possibly, identify a “entrance” threshold that we can use in the simulation.

!!!EXPLAIN BETTER HERE!!!

Comparative analysis

To run the comparison analysis we will need two datasets:

Both dataset need to have in common the same patients so that we can reconstruct the index.

The analysis will be run on two hormon receptos:

ER analysis

IHC dataset

As Input dataset we are choosing to use:

Clinical data downloaded from cBioportal for the dataset: Breast Invasive Carcinoma (TCGA, Cell 2015) - LINK

The dataset has been downloade and stored as brca_tcga_pub2015_clinical_data.tsv.

library(dplyr)
library(ggplot2)
library(plotly)
library(readr)
library(knitr)
ihc <-readr::read_tsv("../external_resources/brca_tcga_pub2015_clinical_data.tsv")
ihcFilter <- ihc %>% 
  dplyr::select(`Patient ID`
                #, `Sample ID`
                , `ER Status By IHC`
                , `ER Status IHC Percent Positive`
                #, `ER positivity scale used`
                #, `ER positivity scale other`
                #, `IHC Score`
                #, `IHC-HER2`
                #, `PR positivity scale used`
                #, `PR status by ihc`
                #, `PR status ihc percent positive`
                ) %>%
  dplyr::filter(!is.na(`ER Status By IHC`)) %>% # Remove the <NA>
  dplyr::filter(!is.na(`ER Status IHC Percent Positive`)) %>% # Remove the <NA>
  dplyr::rename(case_id=`Patient ID`, er_status=`ER Status By IHC`, ihc_value=`ER Status IHC Percent Positive`)
 
# preview
kable(head(ihcFilter), caption="top 6 rows")
case_id er_status ihc_value
TCGA-A2-A3XV Positive <10%
TCGA-A2-A3Y0 Positive 90-99%
TCGA-LL-A50Y Positive 90-99%
TCGA-LL-A5YP Positive <10%
TCGA-LL-A5YL Positive 90-99%
TCGA-LL-A5YM Positive 90-99%

RNA-seq dataset

The RNA-seq dataset was extracted using PTD function.!

case_id expressionValue
TCGA-A1-A0SB -0.9404
TCGA-A1-A0SD -0.1790
TCGA-A1-A0SE -0.6355
TCGA-A1-A0SF -0.3363
TCGA-A1-A0SH -0.9036
TCGA-A1-A0SI -0.6584

Inner Join datasets

df <- dplyr::inner_join(rnaseq, ihcFilter, by="case_id")
DT::datatable(df
          # ADD BUTTONS TO THE TABLE
          , extensions = 'Buttons'
          , options = list(
               dom = 'lBfrtip'
              , buttons = c('copy', 'csv', 'excel')
              )
          , caption = "Comparison between Missing and Submitted regions (bp) in the panel"
          )

Comparison Analysis

Explore RNA-seq Z-score

# explore z-score value
p1 <- ggplot(df, aes(x=expressionValue)) +
        geom_density(kernel="gaussian") + 
        geom_vline(aes(xintercept=0.3, color="red")) + 
        labs(x="Expression z-scores", title="Rna-seq expression density plot") + 
        theme(legend.position = "none", plot.title=element_text(size=10))
p1

Explore ICH values

# barplot 
p2 <- ggplot(data=df, aes(x=ihc_value)) + 
        geom_bar(stat = "count", position = "stack") + 
        labs(title="Barplot with COUNT of patients in each ER ICH expression value (from 0 to 100%)")+
        theme(legend.position = "none", plot.title=element_text(size=10))
p2

Compare

p3 <- ggplot(data=df, aes(x=ihc_value, y=expressionValue, group=1)) +
    geom_point(colour="red", size=1, shape=21, fill="white") +
    labs(title="Comparison between RNA-seq and IHC values for ER in Breast cancer") +
    xlab("IHC value") +
    ylab("RNA-seq z-score") +
    geom_smooth(method="lm") +
    geom_hline(yintercept =0.3) +
    theme(legend.position = "none", plot.title=element_text(size=10))
ggplotly(p3,width = 650, height = 400, margin(t=1000))

Fit to a linear model

# Convert chategorical values to continue numerical value 
# <10% = 1
# 10-19% = 2
# etc..
df$ihc_value2 <- as.numeric(factor(df$ihc_value))
# Fit the data into a linea regressino model ache chek the coefficients
summary(lm(df$expressionValue ~ ihc_value2, df))

Call:
lm(formula = df$expressionValue ~ ihc_value2, data = df)

Residuals:
    Min      1Q  Median      3Q     Max 
-1.1511 -0.5160 -0.1985  0.3118  3.6848 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept) -0.91121    0.10598  -8.598 4.32e-16 ***
ihc_value2   0.10991    0.01292   8.510 7.99e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.7788 on 305 degrees of freedom
Multiple R-squared:  0.1919,    Adjusted R-squared:  0.1892 
F-statistic: 72.42 on 1 and 305 DF,  p-value: 7.986e-16

There is a significant linear relationship between the predictor and the outcome. Although the \(R^2\) value is very low (\(R^2\) indicates the percentage of total variation explained by the linear relationship with the predictors).

  • Pearson correlation: 0.4380399

Put all the plots together

Error: `device` must be NULL, a string or a function.

PR analysis

IHC dataset

ihcPRFilter <- ihc %>% 
  dplyr::select(`Patient ID`
                #, `Sample ID`
                #, `ER Status By IHC`
                #, `ER Status IHC Percent Positive`
                #, `ER positivity scale used`
                #, `ER positivity scale other`
                #, `IHC Score`
                #, `IHC-HER2`
                #, `PR positivity scale used`
                , `PR status by ihc`
                , `PR status ihc percent positive`
                ) %>%
  dplyr::filter(!is.na(`PR status by ihc`)) %>% # Remove the <NA>
  dplyr::filter(!is.na(`PR status ihc percent positive`)) %>% # Remove the <NA>
  dplyr::rename(case_id=`Patient ID`, pr_status=`PR status by ihc`, ihc_value=`PR status ihc percent positive`)

RNA-seq dataset

The RNA-seq dataset was extracted using PTD function.!

panel_design <- data.frame(drug=""
    , gene_symbol="PGR"
    , alteration="expression"
    , exact_alteration="up"
    ,   mutation_specification=""
    ,   group="")


panel <- newCancerPanel(panel_design)
panel <- getAlterations(panel, tumor_type = "brca_tcga_pub2015")
panel <- subsetAlterations(panel)

# Load data from SHIVA retrospective analaysis
#panel <- readRDS("../Temp/shiva_panel.rds")
# Fetch data
rnaseq_PR <- panel@dataFull$expression$data %>%
  filter(tumor_type == "brca") %>%
  filter(gene_symbol == "PGR") %>%
  select(case_id, expressionValue)

Inner join datasets

# join
dfPR <- dplyr::inner_join(rnaseq_PR, ihcPRFilter, by="case_id")

Comparison analysis

Explore RNA-seq Z-score

p1 <- ggplot(dfPR, aes(x=expressionValue)) +
        geom_density(kernel="gaussian") + 
        geom_vline(aes(xintercept=0.3, color="red")) + 
        labs(x="Expression z-scores", title="Rna-seq expression density plot") + 
        theme(legend.position = "none", plot.title=element_text(size=10))
p1

Explore ICH values

p2 <- ggplot(data=dfPR, aes(x=ihc_value)) + 
        geom_bar(stat = "count", position = "stack") + 
        labs(title="Barplot with COUNT of patients in each PR ICH expression value (from 0 to 100%)")+
        theme(legend.position = "none", plot.title=element_text(size=10))
p2

Compare

p3 <- ggplot(data=dfPR, aes(x=ihc_value, y=expressionValue, group=1)) +
    geom_point(colour="red", size=1, shape=21, fill="white") +
    labs(title="Comparison between RNA-seq and IHC values for PR in Breast cancer") +
    xlab("IHC value") +
    ylab("RNA-seq z-score") +
    geom_smooth(method="lm") +
    geom_hline(yintercept =0.3) +
    theme(legend.position = "none", plot.title=element_text(size=10))

ggplotly(p3,width = 650, height = 400, margin(t=1000))

Fit to a linear model

# Convert chategorical values to continue numerical value 
# <10% = 1
# 10-19% = 2
# etc..
dfPR$ihc_value2 <- as.numeric(factor(dfPR$ihc_value))
# Fit the data into a linea regressino model ache chek the coefficients
summary(lm(expressionValue ~ ihc_value2, dfPR))

Put all the plots together

LS0tCnRpdGxlOiAiQ29tcGFyaXNvbiBiZXR3ZWVuIFJOQS1zZXEgYW5kIEltbXVub2hpc3RvY2hlbWlzdHJ5IGRhdGEiCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgY29kZV9mb2xkaW5nOiBoaWRlCiAgICBmaWdfaGVpZ2h0OiA4CiAgICBmaWdfd2lkdGg6IDEwCiAgICBoaWdobGlnaHQ6IGhhZGRvY2sKICAgIHRoZW1lOiByZWFkYWJsZQogICAgdG9jOiB5ZXMKICAgIHRvY19kZXB0aDogMwogICAgdG9jX2Zsb2F0OiB5ZXMKICBodG1sX25vdGVib29rOiBkZWZhdWx0Ci0tLQoKV2UgYXJlIHVzaW5nIHRoZSBTSElWQSB0cmlhbCB0byBydW4gYSByZXRyb3NwZWN0aXZlIGFuYWx5c2lzIHRvIHZhbGlkYXRlIHRoZSBQVEQgcGFja2FnZS4gRHVyaW5nIHRoZSB0cmlhbCwgdGhlIGhvcm1vbiByZWNlcHRvcnMgRVIsIEFSIGFuZCBQUiB3ZXJlIGNvbGVsY3RlZCB1c2luZyBJbW11bm9oaXN0b2NoZW1pc3RyeSAoSUhDKS4gSW4gdGhlIHJldHJvc3BlY3RpdmUgYW5hbGlzaSB3ZSB1c2VkIHRoZSBleHByZXNzaW9uIChhcyB6LXNjb3JlKSB2YWx1ZXMgY29sbGVjdGVkIGZyb20gdGhlIFJOQS1zZXEgZGF0YSBUQ0dBIGRhdGFzZXQuIEluIHRoaXMgc2VjdGlvbiB3ZSB3YW50IHRvIGV4cGxvcmUgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIFJOQS1zZXEgYW5kIEltbXVub2hpc3RvY2hlbWlzdHJ5IGFuZCwgcG9zc2libHksIGlkZW50aWZ5IGEgImVudHJhbmNlIiB0aHJlc2hvbGQgdGhhdCB3ZSBjYW4gdXNlIGluIHRoZSBzaW11bGF0aW9uLgoKISEhRVhQTEFJTiBCRVRURVIgSEVSRSEhIQoKQ29tcGFyYXRpdmUgYW5hbHlzaXMgey50YWJzZXR9Cj09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CgoKVG8gcnVuIHRoZSBjb21wYXJpc29uIGFuYWx5c2lzIHdlIHdpbGwgbmVlZCB0d28gZGF0YXNldHM6CgoqIERhdGFzZXQgd2l0aCBJSEMgdmFsdWVzLCAKKiBEYXRhc2V0IHdpdGggUk5BLXNlcSBleHByZXNpc29uIHZhbHVlcwoKQm90aCBkYXRhc2V0IG5lZWQgdG8gaGF2ZSBpbiBjb21tb24gdGhlIHNhbWUgcGF0aWVudHMgc28gdGhhdCB3ZSBjYW4gcmVjb25zdHJ1Y3QgdGhlIGluZGV4LgoKVGhlIGFuYWx5c2lzIHdpbGwgYmUgcnVuIG9uIHR3byBob3Jtb24gcmVjZXB0b3M6IAoKKiBFUgoqIFBSCgoKRVIgYW5hbHlzaXMgCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgojIyMgSUhDIGRhdGFzZXQKCkFzIElucHV0IGRhdGFzZXQgd2UgYXJlIGNob29zaW5nIHRvIHVzZTogCgpDbGluaWNhbCBkYXRhIGRvd25sb2FkZWQgZnJvbSBjQmlvcG9ydGFsIGZvciB0aGUgZGF0YXNldDogKipCcmVhc3QgSW52YXNpdmUgQ2FyY2lub21hIChUQ0dBLCBDZWxsIDIwMTUpKiogLSBbTElOS10oaHR0cHM6Ly9naXQuaWVvLmV1L2FjYy1iaW9pbmZvL21ldGEvYWN0aXZpdHkpCgpUaGUgZGF0YXNldCBoYXMgYmVlbiBkb3dubG9hZGUgYW5kIHN0b3JlZCBhcyAgYGBgYnJjYV90Y2dhX3B1YjIwMTVfY2xpbmljYWxfZGF0YS50c3ZgYGAuIAoKYGBge3IsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShwbG90bHkpCmxpYnJhcnkocmVhZHIpCmxpYnJhcnkoa25pdHIpCmxpYnJhcnkoUHJlY2lzaW9uVHJpYWxEZXNpZ25lcikKCmloYyA8LXJlYWRyOjpyZWFkX3RzdigiLi4vZXh0ZXJuYWxfcmVzb3VyY2VzL2JyY2FfdGNnYV9wdWIyMDE1X2NsaW5pY2FsX2RhdGEudHN2IikKaWhjRmlsdGVyIDwtIGloYyAlPiUgCiAgZHBseXI6OnNlbGVjdChgUGF0aWVudCBJRGAKICAgICAgICAgICAgICAgICMsIGBTYW1wbGUgSURgCiAgICAgICAgICAgICAgICAsIGBFUiBTdGF0dXMgQnkgSUhDYAogICAgICAgICAgICAgICAgLCBgRVIgU3RhdHVzIElIQyBQZXJjZW50IFBvc2l0aXZlYAogICAgICAgICAgICAgICAgIywgYEVSIHBvc2l0aXZpdHkgc2NhbGUgdXNlZGAKICAgICAgICAgICAgICAgICMsIGBFUiBwb3NpdGl2aXR5IHNjYWxlIG90aGVyYAogICAgICAgICAgICAgICAgIywgYElIQyBTY29yZWAKICAgICAgICAgICAgICAgICMsIGBJSEMtSEVSMmAKICAgICAgICAgICAgICAgICMsIGBQUiBwb3NpdGl2aXR5IHNjYWxlIHVzZWRgCiAgICAgICAgICAgICAgICAjLCBgUFIgc3RhdHVzIGJ5IGloY2AKICAgICAgICAgICAgICAgICMsIGBQUiBzdGF0dXMgaWhjIHBlcmNlbnQgcG9zaXRpdmVgCiAgICAgICAgICAgICAgICApICU+JQogIGRwbHlyOjpmaWx0ZXIoIWlzLm5hKGBFUiBTdGF0dXMgQnkgSUhDYCkpICU+JSAjIFJlbW92ZSB0aGUgPE5BPgogIGRwbHlyOjpmaWx0ZXIoIWlzLm5hKGBFUiBTdGF0dXMgSUhDIFBlcmNlbnQgUG9zaXRpdmVgKSkgJT4lICMgUmVtb3ZlIHRoZSA8TkE+CiAgZHBseXI6OnJlbmFtZShjYXNlX2lkPWBQYXRpZW50IElEYCwgZXJfc3RhdHVzPWBFUiBTdGF0dXMgQnkgSUhDYCwgaWhjX3ZhbHVlPWBFUiBTdGF0dXMgSUhDIFBlcmNlbnQgUG9zaXRpdmVgKQogCiMgcHJldmlldwprYWJsZShoZWFkKGloY0ZpbHRlciksIGNhcHRpb249InRvcCA2IHJvd3MiKQpgYGAKCgojIyMgUk5BLXNlcSBkYXRhc2V0CgpUaGUgUk5BLXNlcSBkYXRhc2V0IHdhcyBleHRyYWN0ZWQgdXNpbmcgUFREIGZ1bmN0aW9uLiEKCmBgYHtyfQpwYW5lbF9kZXNpZ24gPC0gZGF0YS5mcmFtZShkcnVnPSIiCiAgICAsIGdlbmVfc3ltYm9sPSJFU1IxIgogICAgLCBhbHRlcmF0aW9uPSJleHByZXNzaW9uIgogICAgLCBleGFjdF9hbHRlcmF0aW9uPSJ1cCIKICAgICwJbXV0YXRpb25fc3BlY2lmaWNhdGlvbj0iIgogICAgLAlncm91cD0iIikKCgpwYW5lbCA8LSBuZXdDYW5jZXJQYW5lbChwYW5lbF9kZXNpZ24pCnBhbmVsIDwtIGdldEFsdGVyYXRpb25zKHBhbmVsLCB0dW1vcl90eXBlID0gImJyY2FfdGNnYV9wdWIyMDE1IikKcGFuZWwgPC0gc3Vic2V0QWx0ZXJhdGlvbnMocGFuZWwpCgojIExvYWQgZGF0YSBmcm9tIFNISVZBIHJldHJvc3BlY3RpdmUgYW5hbGF5c2lzCiNwYW5lbCA8LSByZWFkUkRTKCIuLi9UZW1wL3NoaXZhX3BhbmVsLnJkcyIpCgojIEZldGNoIGRhdGEKcm5hc2VxIDwtIHBhbmVsQGRhdGFGdWxsJGV4cHJlc3Npb24kZGF0YSAlPiUKICBmaWx0ZXIodHVtb3JfdHlwZSA9PSAiYnJjYSIpICU+JQogIGZpbHRlcihnZW5lX3N5bWJvbCA9PSAiRVNSMSIpICU+JQogIHNlbGVjdChjYXNlX2lkLCBleHByZXNzaW9uVmFsdWUpCgojIFByZXZpZXcKa2FibGUoaGVhZChybmFzZXEpLCBjYXB0aW9uID0gInRvcCA2IHJvd3MiKQpgYGAKCgojIyMgSW5uZXIgSm9pbiBkYXRhc2V0cwoKYGBge3J9CmRmIDwtIGRwbHlyOjppbm5lcl9qb2luKHJuYXNlcSwgaWhjRmlsdGVyLCBieT0iY2FzZV9pZCIpCkRUOjpkYXRhdGFibGUoZGYKICAgICAgICAgICMgQUREIEJVVFRPTlMgVE8gVEhFIFRBQkxFCiAgICAgICAgICAsIGV4dGVuc2lvbnMgPSAnQnV0dG9ucycKICAgICAgICAgICwgb3B0aW9ucyA9IGxpc3QoCiAgICAgICAgICAgICAgIGRvbSA9ICdsQmZydGlwJwogICAgICAgICAgICAgICwgYnV0dG9ucyA9IGMoJ2NvcHknLCAnY3N2JywgJ2V4Y2VsJykKICAgICAgICAgICAgICApCiAgICAgICAgICAsIGNhcHRpb24gPSAiQ29tcGFyaXNvbiBiZXR3ZWVuIE1pc3NpbmcgYW5kIFN1Ym1pdHRlZCByZWdpb25zIChicCkgaW4gdGhlIHBhbmVsIgogICAgICAgICAgKQpgYGAKCgojIyMgQ29tcGFyaXNvbiBBbmFseXNpcwoKCgojIyMjIEV4cGxvcmUgUk5BLXNlcSBaLXNjb3JlIAoKYGBge3J9CiMgZXhwbG9yZSB6LXNjb3JlIHZhbHVlCnAxIDwtIGdncGxvdChkZiwgYWVzKHg9ZXhwcmVzc2lvblZhbHVlKSkgKwogICAgICAgIGdlb21fZGVuc2l0eShrZXJuZWw9ImdhdXNzaWFuIikgKyAKICAgICAgICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0PTAuMywgY29sb3I9InJlZCIpKSArIAogICAgICAgIGxhYnMoeD0iRXhwcmVzc2lvbiB6LXNjb3JlcyIsIHRpdGxlPSJSbmEtc2VxIGV4cHJlc3Npb24gZGVuc2l0eSBwbG90IikgKyAKICAgICAgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsIHBsb3QudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9MTApKQpwMQoKCmdnc2F2ZShmaWxlbmFtZT0iLi4vRmlndXJlcy9maWdfZXh0cmExLnN2ZyIsIHBsb3Q9cDEsIGRldmljZSA9ICJzdmciKQpgYGAKCiMjIyMgRXhwbG9yZSBJQ0ggdmFsdWVzCgpgYGB7cn0KIyBiYXJwbG90IApwMiA8LSBnZ3Bsb3QoZGF0YT1kZiwgYWVzKHg9aWhjX3ZhbHVlKSkgKyAKICAgICAgICBnZW9tX2JhcihzdGF0ID0gImNvdW50IiwgcG9zaXRpb24gPSAic3RhY2siKSArIAogICAgICAgIGxhYnModGl0bGU9IkJhcnBsb3Qgd2l0aCBDT1VOVCBvZiBwYXRpZW50cyBpbiBlYWNoIEVSIElDSCBleHByZXNzaW9uIHZhbHVlIChmcm9tIDAgdG8gMTAwJSkiKSsKICAgICAgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsIHBsb3QudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9MTApKQpwMgoKZ2dzYXZlKGZpbGVuYW1lPSIuLi9GaWd1cmVzL2ZpZ19leHRyYTIuc3ZnIiwgcGxvdD1wMiwgZGV2aWNlID0gInN2ZyIpCmBgYAoKCiMjIyMgQ29tcGFyZQoKYGBge3IsIGZpZy53aWR0aD03fQpwMyA8LSBnZ3Bsb3QoZGF0YT1kZiwgYWVzKHg9aWhjX3ZhbHVlLCB5PWV4cHJlc3Npb25WYWx1ZSwgZ3JvdXA9MSkpICsKICAgIGdlb21fcG9pbnQoY29sb3VyPSJyZWQiLCBzaXplPTEsIHNoYXBlPTIxLCBmaWxsPSJ3aGl0ZSIpICsKICAgIGxhYnModGl0bGU9IkNvbXBhcmlzb24gYmV0d2VlbiBSTkEtc2VxIGFuZCBJSEMgdmFsdWVzIGZvciBFUiBpbiBCcmVhc3QgY2FuY2VyIikgKwogICAgeGxhYigiSUhDIHZhbHVlIikgKwogICAgeWxhYigiUk5BLXNlcSB6LXNjb3JlIikgKwogICAgZ2VvbV9zbW9vdGgobWV0aG9kPSJsbSIpICsKICAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9MC4zKSArCiAgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsIHBsb3QudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9MTApKQoKZ2dwbG90bHkocDMsd2lkdGggPSA2NTAsIGhlaWdodCA9IDQwMCwgbWFyZ2luKHQ9MTAwMCkpCgpnZ3NhdmUoZmlsZW5hbWU9Ii4uL0ZpZ3VyZXMvZmlnX2V4dHJhMy5zdmciLCBwbG90PXAzLCBkZXZpY2UgPSAic3ZnIikKYGBgCgoKIyMjIyBGaXQgdG8gYSBsaW5lYXIgbW9kZWwKCgpgYGB7cn0KIyBDb252ZXJ0IGNoYXRlZ29yaWNhbCB2YWx1ZXMgdG8gY29udGludWUgbnVtZXJpY2FsIHZhbHVlIAojIDwxMCUgPSAxCiMgMTAtMTklID0gMgojIGV0Yy4uCmRmJGloY192YWx1ZTIgPC0gYXMubnVtZXJpYyhmYWN0b3IoZGYkaWhjX3ZhbHVlKSkKIyBGaXQgdGhlIGRhdGEgaW50byBhIGxpbmVhIHJlZ3Jlc3Npbm8gbW9kZWwgYWNoZSBjaGVrIHRoZSBjb2VmZmljaWVudHMKc3VtbWFyeShsbShkZiRleHByZXNzaW9uVmFsdWUgfiBpaGNfdmFsdWUyLCBkZikpCmBgYAoKVGhlcmUgaXMgYSBzaWduaWZpY2FudCBsaW5lYXIgcmVsYXRpb25zaGlwIGJldHdlZW4gdGhlIHByZWRpY3RvciBhbmQgdGhlIG91dGNvbWUuIEFsdGhvdWdoIHRoZSAkUl4yJCB2YWx1ZSBpcyB2ZXJ5IGxvdyAoJFJeMiQgaW5kaWNhdGVzIHRoZSBwZXJjZW50YWdlIG9mIHRvdGFsIHZhcmlhdGlvbiBleHBsYWluZWQgYnkgdGhlIGxpbmVhciByZWxhdGlvbnNoaXAgd2l0aCB0aGUgcHJlZGljdG9ycykuIAoKKiAgUGVhcnNvbiBjb3JyZWxhdGlvbjogKipgciBjb3IoYXMubnVtZXJpYyhkZiRpaGNfdmFsdWUyKSwgZGYkZXhwcmVzc2lvblZhbHVlKWAqKgoKIyMjIFB1dCBhbGwgdGhlIHBsb3RzIHRvZ2V0aGVyCgoKYGBge3IsIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTEyLCBlY2hvPUZBTFNFfQpsaWJyYXJ5KGdyaWQpCmxpYnJhcnkoZ3JpZEV4dHJhKQpncmlkLm5ld3BhZ2UoKQpwdXNoVmlld3BvcnQodmlld3BvcnQobGF5b3V0ID0gZ3JpZC5sYXlvdXQoMiwgMikpKQoKcHJpbnQocDEgKyBjb29yZF9mbGlwKCksIHZwID0gdmlld3BvcnQobGF5b3V0LnBvcy5yb3cgPSAxLCBsYXlvdXQucG9zLmNvbCA9IDEpKQpwcmludChwMywgdnAgPSB2aWV3cG9ydChsYXlvdXQucG9zLnJvdyA9IDEsIGxheW91dC5wb3MuY29sID0gMikpCnByaW50KHAyLCB2cCA9IHZpZXdwb3J0KGxheW91dC5wb3Mucm93ID0gMiwgbGF5b3V0LnBvcy5jb2wgPSAyKSkKYGBgCgoKUFIgYW5hbHlzaXMKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCiMjIyBJSEMgZGF0YXNldAoKYGBge3J9CmloY1BSRmlsdGVyIDwtIGloYyAlPiUgCiAgZHBseXI6OnNlbGVjdChgUGF0aWVudCBJRGAKICAgICAgICAgICAgICAgICMsIGBTYW1wbGUgSURgCiAgICAgICAgICAgICAgICAjLCBgRVIgU3RhdHVzIEJ5IElIQ2AKICAgICAgICAgICAgICAgICMsIGBFUiBTdGF0dXMgSUhDIFBlcmNlbnQgUG9zaXRpdmVgCiAgICAgICAgICAgICAgICAjLCBgRVIgcG9zaXRpdml0eSBzY2FsZSB1c2VkYAogICAgICAgICAgICAgICAgIywgYEVSIHBvc2l0aXZpdHkgc2NhbGUgb3RoZXJgCiAgICAgICAgICAgICAgICAjLCBgSUhDIFNjb3JlYAogICAgICAgICAgICAgICAgIywgYElIQy1IRVIyYAogICAgICAgICAgICAgICAgIywgYFBSIHBvc2l0aXZpdHkgc2NhbGUgdXNlZGAKICAgICAgICAgICAgICAgICwgYFBSIHN0YXR1cyBieSBpaGNgCiAgICAgICAgICAgICAgICAsIGBQUiBzdGF0dXMgaWhjIHBlcmNlbnQgcG9zaXRpdmVgCiAgICAgICAgICAgICAgICApICU+JQogIGRwbHlyOjpmaWx0ZXIoIWlzLm5hKGBQUiBzdGF0dXMgYnkgaWhjYCkpICU+JSAjIFJlbW92ZSB0aGUgPE5BPgogIGRwbHlyOjpmaWx0ZXIoIWlzLm5hKGBQUiBzdGF0dXMgaWhjIHBlcmNlbnQgcG9zaXRpdmVgKSkgJT4lICMgUmVtb3ZlIHRoZSA8TkE+CiAgZHBseXI6OnJlbmFtZShjYXNlX2lkPWBQYXRpZW50IElEYCwgcHJfc3RhdHVzPWBQUiBzdGF0dXMgYnkgaWhjYCwgaWhjX3ZhbHVlPWBQUiBzdGF0dXMgaWhjIHBlcmNlbnQgcG9zaXRpdmVgKQpgYGAKCiMjIyBSTkEtc2VxIGRhdGFzZXQKClRoZSBSTkEtc2VxIGRhdGFzZXQgd2FzIGV4dHJhY3RlZCB1c2luZyBQVEQgZnVuY3Rpb24uIQoKYGBge3J9CnBhbmVsX2Rlc2lnbiA8LSBkYXRhLmZyYW1lKGRydWc9IiIKICAgICwgZ2VuZV9zeW1ib2w9IlBHUiIKICAgICwgYWx0ZXJhdGlvbj0iZXhwcmVzc2lvbiIKICAgICwgZXhhY3RfYWx0ZXJhdGlvbj0idXAiCiAgICAsCW11dGF0aW9uX3NwZWNpZmljYXRpb249IiIKICAgICwJZ3JvdXA9IiIpCgoKcGFuZWwgPC0gbmV3Q2FuY2VyUGFuZWwocGFuZWxfZGVzaWduKQpwYW5lbCA8LSBnZXRBbHRlcmF0aW9ucyhwYW5lbCwgdHVtb3JfdHlwZSA9ICJicmNhX3RjZ2FfcHViMjAxNSIpCnBhbmVsIDwtIHN1YnNldEFsdGVyYXRpb25zKHBhbmVsKQoKIyBMb2FkIGRhdGEgZnJvbSBTSElWQSByZXRyb3NwZWN0aXZlIGFuYWxheXNpcwojcGFuZWwgPC0gcmVhZFJEUygiLi4vVGVtcC9zaGl2YV9wYW5lbC5yZHMiKQojIEZldGNoIGRhdGEKcm5hc2VxX1BSIDwtIHBhbmVsQGRhdGFGdWxsJGV4cHJlc3Npb24kZGF0YSAlPiUKICBmaWx0ZXIodHVtb3JfdHlwZSA9PSAiYnJjYSIpICU+JQogIGZpbHRlcihnZW5lX3N5bWJvbCA9PSAiUEdSIikgJT4lCiAgc2VsZWN0KGNhc2VfaWQsIGV4cHJlc3Npb25WYWx1ZSkKYGBgCgojIyMgSW5uZXIgam9pbiBkYXRhc2V0cwoKYGBge3J9CiMgam9pbgpkZlBSIDwtIGRwbHlyOjppbm5lcl9qb2luKHJuYXNlcV9QUiwgaWhjUFJGaWx0ZXIsIGJ5PSJjYXNlX2lkIikKYGBgCgoKIyMjIENvbXBhcmlzb24gYW5hbHlzaXMKCiMjIyMgRXhwbG9yZSBSTkEtc2VxIFotc2NvcmUgCgpgYGB7cn0KcDEgPC0gZ2dwbG90KGRmUFIsIGFlcyh4PWV4cHJlc3Npb25WYWx1ZSkpICsKICAgICAgICBnZW9tX2RlbnNpdHkoa2VybmVsPSJnYXVzc2lhbiIpICsgCiAgICAgICAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdD0wLjMsIGNvbG9yPSJyZWQiKSkgKyAKICAgICAgICBsYWJzKHg9IkV4cHJlc3Npb24gei1zY29yZXMiLCB0aXRsZT0iUm5hLXNlcSBleHByZXNzaW9uIGRlbnNpdHkgcGxvdCIpICsgCiAgICAgICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLCBwbG90LnRpdGxlPWVsZW1lbnRfdGV4dChzaXplPTEwKSkKcDEKYGBgCgoKIyMjIyBFeHBsb3JlIElDSCB2YWx1ZXMKCmBgYHtyfQpwMiA8LSBnZ3Bsb3QoZGF0YT1kZlBSLCBhZXMoeD1paGNfdmFsdWUpKSArIAogICAgICAgIGdlb21fYmFyKHN0YXQgPSAiY291bnQiLCBwb3NpdGlvbiA9ICJzdGFjayIpICsgCiAgICAgICAgbGFicyh0aXRsZT0iQmFycGxvdCB3aXRoIENPVU5UIG9mIHBhdGllbnRzIGluIGVhY2ggUFIgSUNIIGV4cHJlc3Npb24gdmFsdWUgKGZyb20gMCB0byAxMDAlKSIpKwogICAgICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwgcGxvdC50aXRsZT1lbGVtZW50X3RleHQoc2l6ZT0xMCkpCnAyCmBgYAoKCgojIyMjIENvbXBhcmUKCmBgYHtyLCBmaWcud2lkdGg9N30KcDMgPC0gZ2dwbG90KGRhdGE9ZGZQUiwgYWVzKHg9aWhjX3ZhbHVlLCB5PWV4cHJlc3Npb25WYWx1ZSwgZ3JvdXA9MSkpICsKICAgIGdlb21fcG9pbnQoY29sb3VyPSJyZWQiLCBzaXplPTEsIHNoYXBlPTIxLCBmaWxsPSJ3aGl0ZSIpICsKICAgIGxhYnModGl0bGU9IkNvbXBhcmlzb24gYmV0d2VlbiBSTkEtc2VxIGFuZCBJSEMgdmFsdWVzIGZvciBQUiBpbiBCcmVhc3QgY2FuY2VyIikgKwogICAgeGxhYigiSUhDIHZhbHVlIikgKwogICAgeWxhYigiUk5BLXNlcSB6LXNjb3JlIikgKwogICAgZ2VvbV9zbW9vdGgobWV0aG9kPSJsbSIpICsKICAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9MC4zKSArCiAgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsIHBsb3QudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9MTApKQoKZ2dwbG90bHkocDMsd2lkdGggPSA2NTAsIGhlaWdodCA9IDQwMCwgbWFyZ2luKHQ9MTAwMCkpCmBgYAoKCiMjIyMgRml0IHRvIGEgbGluZWFyIG1vZGVsCgpgYGB7cn0KIyBDb252ZXJ0IGNoYXRlZ29yaWNhbCB2YWx1ZXMgdG8gY29udGludWUgbnVtZXJpY2FsIHZhbHVlIAojIDwxMCUgPSAxCiMgMTAtMTklID0gMgojIGV0Yy4uCmRmUFIkaWhjX3ZhbHVlMiA8LSBhcy5udW1lcmljKGZhY3RvcihkZlBSJGloY192YWx1ZSkpCiMgRml0IHRoZSBkYXRhIGludG8gYSBsaW5lYSByZWdyZXNzaW5vIG1vZGVsIGFjaGUgY2hlayB0aGUgY29lZmZpY2llbnRzCnN1bW1hcnkobG0oZXhwcmVzc2lvblZhbHVlIH4gaWhjX3ZhbHVlMiwgZGZQUikpCmBgYAoKIyMjIFB1dCBhbGwgdGhlIHBsb3RzIHRvZ2V0aGVyCgoKYGBge3IsIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTEyLCBlY2hvPUZBTFNFfQpsaWJyYXJ5KGdyaWQpCmdyaWQubmV3cGFnZSgpCnB1c2hWaWV3cG9ydCh2aWV3cG9ydChsYXlvdXQgPSBncmlkLmxheW91dCgyLCAyKSkpCgpwcmludChwMSArIGNvb3JkX2ZsaXAoKSwgdnAgPSB2aWV3cG9ydChsYXlvdXQucG9zLnJvdyA9IDEsIGxheW91dC5wb3MuY29sID0gMSkpCnByaW50KHAzLCB2cCA9IHZpZXdwb3J0KGxheW91dC5wb3Mucm93ID0gMSwgbGF5b3V0LnBvcy5jb2wgPSAyKSkKcHJpbnQocDIsIHZwID0gdmlld3BvcnQobGF5b3V0LnBvcy5yb3cgPSAyLCBsYXlvdXQucG9zLmNvbCA9IDIpKQoKYGBg